/**
 * Licensed under the Apache License Version 2.0.
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package net.interknit.knitter.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import net.interknit.knitter.client.java.JavaSourceWriterFactory;
import net.interknit.knitter.client.java.JavaSourceWriterUtils;
import net.interknit.knitter.client.layout.EndpointEl;
import net.interknit.knitter.client.layout.EndpointXml;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;

/**
 *
 */
public class CodeGenTask extends Task
{
	private static SourceWriterFactory factory;

	private static final String defaultPackageName = "";
	private static final String defaultSourceDirectory = "./client";
	private static final String defaultSourceWriterFactory = JavaSourceWriterFactory.class.getName();

	private String url;
	private String srcdir;
	private String packagename;
	private String appendDerivedPackageName;
	private String sourceWriterFactory;

	/**
	 * @param url the url to set
	 */
	public void setUrl(String url)
	{
		this.url = url;
	}

	/**
	 * @param srcdir the srcdir to set
	 */
	public void setSrcdir(String srcdir)
	{
		this.srcdir = srcdir;
	}

	/**
	 * @param packagename the packagename to set
	 */
	public void setPackagename(String packagename)
	{
		this.packagename = packagename;
	}

	/**
	 * @param sourceWriterFactory the sourceWriterFactory to set
	 */
	public void setSourceWriterFactory(String sourceWriterFactory)
	{
		this.sourceWriterFactory = sourceWriterFactory;
	}

	/**
	 * @param appendDerivedPackageName the appendDerivedPackageName to set
	 */
	public void setAppendDerivedPackageName(String appendDerivedPackageName)
	{
		this.appendDerivedPackageName = appendDerivedPackageName;
	}

	/* (non-Javadoc)
	 * @see org.apache.tools.ant.Task#execute()
	 */
	@Override
	public void execute() throws BuildException
	{
		generate();
	}

	private void generate() throws BuildException
	{
		try
		{
			if(url == null || "".equals(url.trim()))
				throw new RuntimeException("url (-u) cannot be null or empty.");

			if(srcdir == null || "".equals(srcdir.trim()))
			{
				srcdir = defaultSourceDirectory;
				System.out.println("srcdir (-d) not specified. default will be used: " + srcdir);
			}

			if(packagename == null || "".equals(packagename.trim()))
			{
				packagename = defaultPackageName;
				System.out.println("packagename (-p) not specified. default will be used: " + packagename);
			}

			if(appendDerivedPackageName == null || "".equals(appendDerivedPackageName.trim()))
			{
				appendDerivedPackageName = "false";
				System.out.println("appendDerivedPackageName (-appendDerivedPackageName) not specified. default will be used: " + appendDerivedPackageName);
			}

			if(sourceWriterFactory == null || "".equals(sourceWriterFactory.trim()))
			{
				sourceWriterFactory = defaultSourceWriterFactory;
				System.out.println("sourceWriterFactory (-sourceWriterFactory) not specified.  default will be used: " + sourceWriterFactory);
			}

			File srcDir = new File(srcdir);
			srcDir.mkdirs();

			factory = (SourceWriterFactory) Class.forName(sourceWriterFactory).newInstance();

			InputStream def = null;

			try
			{
				URL targetUrl = new URL(url);

				def = targetUrl.openStream();
			}
			catch(MalformedURLException murle)
			{
				System.err.println(url + " is not a valid URL; will try to read it as a File object.");

				try
				{
					def = new FileInputStream(url);
				}
				catch(FileNotFoundException fnfe)
				{
					throw new RuntimeException(murle);
				}
			}

			EndpointEl endpointEl = new EndpointXml(def).getEndpoint();

			packagename = JavaSourceWriterUtils.createValidVariableName(packagename);

			if(new Boolean(appendDerivedPackageName).booleanValue())
			{
				if(packagename != null && ! packagename.isEmpty())
				{
					packagename += ".";
				}
				else
				{
					packagename = "";
				}

				packagename +=
						JavaSourceWriterUtils.unqualifiedClassName(
								endpointEl.getName()).toLowerCase();
			}

			SourceWriter sourceWriter = factory.create(endpointEl);
			sourceWriter.write(srcDir, packagename);
		}
		catch(Exception e)
		{
			throw new BuildException(e);
		}
	}

	public static SourceWriterFactory getSourceWriterFactory()
	{
		return factory;
	}
}
